package logic.nodes.lod.blocks;

import gameStates.absGamesStates.AbsIngameState;

import java.util.ArrayList;
import java.util.List;

import settings.GraphicSettings;

import com.jme.math.Vector3f;
import logic.nodes.collision.CollisionDetector;
import logic.nodes.collision.CollidableNode;
import logic.nodes.lod.LODNode;
import logic.ships.moveableShip.MovableShip;
import logic.weapons.Weapon;
import logic.weapons.WeaponFire;

public class LeafBlock extends AbstractBlock {
		
	public static final float VIEW_DIST = 900f;
	public static final float UPDATE_DIST = 400f;
	public static final float MIN_LOD_VIEW_DIST = 500f;
	private static final float MIN_PARTICLE_DIST = 200;
	private static final float MAX_PARTICLE_DIST = 400;
	
	public static float particleDist;
	
	public static final List<LeafBlock> allLeafBlocks = new ArrayList<LeafBlock>();
	
	private static int LEAF_INDEX;
	
	private List<CollidableNode> nodes, noWeaponFireNodes, weaponFireNodes;
	private List<LODNode> lodNodes;
	
	private CollisionDetector collisionDetector;
	
	private int leafIndex;
	
	public LeafBlock(Vector3f center, float size, AbsIngameState ingameState) {
		super(center, size, ingameState);
		
		leafIndex = LEAF_INDEX;
		LEAF_INDEX++;
		
		nodes = new ArrayList<CollidableNode>();
		
		noWeaponFireNodes = new ArrayList<CollidableNode>();
		weaponFireNodes = new ArrayList<CollidableNode>();
		
		lodNodes = new ArrayList<LODNode>();
		
		allLeafBlocks.add(this);
		
		collisionDetector = new CollisionDetector(this);
		ingameState.getThreadPool().registerController(collisionDetector);
	}
	
	public void addLeafNode(CollidableNode node) {
		assert(!(node instanceof Weapon));
		
		nodes.add(node);
		if(node instanceof WeaponFire) weaponFireNodes.add(node);
		else noWeaponFireNodes.add(node);
		
		if(node instanceof LODNode) lodNodes.add((LODNode)node);
		
		node.getLeafBlocks().add(this);
	}
	
	public void removeLeafNode(CollidableNode node) {
		nodes.remove(node);
		noWeaponFireNodes.remove(node);
		weaponFireNodes.remove(node);
		lodNodes.remove(node);
	}
		
	public List<CollidableNode> getLeafNodes() { return nodes; }
	
	public List<CollidableNode> getNoneWeaponFireNodes() { return noWeaponFireNodes; }
	
	public List<CollidableNode> getWeaponFireNodes() { return weaponFireNodes; }
	
	public List<LODNode> getLODNodes() { return lodNodes; }
	
	public float getSize() { return box.xExtent; }
	
	public void updateGeometrySettings() {
		for(LODNode node : lodNodes) {
			node.updateGeometrySettings();
		}
	}
	
	public void updateTextureSettings() {
		for(LODNode node : lodNodes) {
			node.updateTextureQuality();
		}
	}
	
	public void updateTextureFilters() {
		for(LODNode node : lodNodes) {
			node.updateTextureFilters();
		}
	}
	
	public void updateTrailQuality() {
		for(LODNode node : lodNodes) {
			if(node instanceof MovableShip) {
				MovableShip ship = (MovableShip)node;
				ship.updateTrailQuality();
			}
		}
	}
	
	public static boolean isVisible(Vector3f loc, AbsIngameState ingameState) {
		return loc.distance(ingameState.getCam().getLocation()) <= particleDist;
	}
	
	public static void updateViewDist() {
		float multiplicator = GraphicSettings.get().getLOD();
		particleDist = MIN_PARTICLE_DIST + (multiplicator * (MAX_PARTICLE_DIST - MIN_PARTICLE_DIST));
	}
	
	@Override
	public boolean equals(Object obj) { return this == obj; }
	
	@Override
	public int hashCode() { return leafIndex; }
}